import {
  BadRequestException,
  HttpException,
  HttpStatus,
  Injectable,
} from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { InjectRepository } from '@nestjs/typeorm';
import { Model } from 'mongoose';
import {
  ApiTagGetResult,
  ApiTagGetResultItem,
} from 'src/types/modules/tag/dto/get-tag.dto';
import { Tag } from 'src/types/modules/tag/entities/tag.type';

@Injectable()
export class TagService {
  constructor(@InjectModel('tag') private tagModel: Model<Tag>) {}

  /**
   * 补全数组-追加被遗失的父标签
   */
  async getTagsAllParent(
    type: number,
    tags: number[],
    user_id: number,
  ): Promise<number[]> {
    // 获取指定标签类型下的所有标签
    const allTags = await this.getAllTags(
      type,
      user_id,
      'tag_id,tag_parent_id',
    );
    console.log('[all tags] ', allTags);
    // 声明空数组存储所有标签
    let allTagsAndParent: number[] = tags;
    // 遍历并找到丢失的父级标签、追加入数组
    function fn(tag_id: number) {
      for (let i = 0, l = allTags.length; i < l; i++) {
        const item = allTags[i];
        if (item.id === tag_id && item.tag_parent_id) {
          // 去重
          const index = allTagsAndParent.findIndex((n: number | string) => {
            return n === item.tag_parent_id;
          });
          if (index < 0) {
            allTagsAndParent.push(item.tag_parent_id);
          }
          // 继续遍历下一级
          fn(item.tag_parent_id);
        }
      }
    }
    for (let i = 0, l = allTagsAndParent.length; i < l; i++) {
      const item = allTagsAndParent[i];
      fn(item);
    }
    // 返回新数组/ids 必须保证返回的是array
    console.log('allTagsAndParent:', allTagsAndParent);
    // 去重
    allTagsAndParent = Array.from(new Set(allTagsAndParent));
    return allTagsAndParent;
  }

  /**
   * 补全数组-追加被遗失的父标签
   */
  async getTagsAllChild(
    type: number,
    tags: number[],
    user_id: number,
  ): Promise<number[]> {
    // 获取指定标签类型下的所有标签
    const allTags = await this.getAllTags(
      type,
      user_id,
      'tag_id,tag_parent_id',
    );
    // console.log('[all tags] ', allTags);
    // 声明空数组存储所有标签
    let allTagsAndChilds: number[] = tags;
    // 遍历并找到丢失的父级标签、追加入数组
    function fn(tag_id: number) {
      for (let i = 0, l = allTags.length; i < l; i++) {
        const item = allTags[i];
        if (item.tag_parent_id && item.tag_parent_id === tag_id) {
          // 去重
          const index = allTagsAndChilds.findIndex((n: number | string) => {
            return n === item.id;
          });
          if (index < 0) {
            allTagsAndChilds.push(item.id);
          }
          // 继续遍历下一级
          fn(item.id);
        }
      }
    }
    for (let i = 0, l = allTagsAndChilds.length; i < l; i++) {
      const item = allTagsAndChilds[i];
      fn(item);
    }
    // 返回新数组/ids 必须保证返回的是array
    // console.log('allTagsAndChilds:', allTagsAndChilds);
    // 去重
    allTagsAndChilds = Array.from(new Set(allTagsAndChilds));
    return allTagsAndChilds;
  }

  /**
   * 获取指定类型所有标签
   * @param {number} [type] [标签类型]
   * @return {array} [数组]
   */
  async getAllTags(type: number, user_id: number, fields?: string) {
    return [];
  }

  /**
   * 获取标签列表
   */
  async getAll(
    type: string,
    teamId: number,
    keywords?: string,
    parentId?: string,
  ): Promise<ApiTagGetResult> {
    const list = await this.tagModel.find({
      type,
      teamId,
    }).sort({ sort: 1 });
    return {
      list,
      tree: await this.getTree(JSON.parse(JSON.stringify(list)), parentId),
    };
  }

  /**
   * 获取分类树，指定分类则返回指定分类及其子分类，不指定则返回所有分类树
   */
  async getTree(list: Tag[], parentId?: string) {
    // 遍历
    function fn(data: Array<ApiTagGetResultItem>, pid: string, zIndex = 0) {
      const result = [];
      let children;
      for (let i = 0, l = data.length; i < l; i++) {
        const tag = data[i];
        tag.title = tag.name;
        tag.label = tag.name;
        tag.value = tag._id;
        tag.type = tag.nodeType;
        tag.key = tag._id;
        if (tag.parentId === pid) {
          tag.zIndex = zIndex;
          children = fn(data, tag._id, zIndex + 1);
          if (children?.length > 0) {
            tag.children = children;
          }
          result.push(tag);
        }
      }
      return result;
    }
    return fn(list, parentId, 0);
  }

  /**
   * 删除标签
   * @param tagId 标签ID
   */
  async deleteById(tagId: string, teamId: number) {
    const deleteRes = await this.tagModel.deleteOne({
      teamId,
      _id: tagId,
    });
    // 判断是否可删除 判断是否有子标签
    return {
      deletedCount: deleteRes.deletedCount,
    };
  }
}
